home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 October: Technology Seed / ADC Seed CD - October 1999.toast / FireWire / FireWire_2.1_SDK_DR3 / Source / FWiX / FWiXDriver / FWiXDriver.c next >
Encoding:
Text File  |  1999-05-17  |  66.2 KB  |  2,175 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FWiXDriver.c
  3.  
  4.     Contains:    Driver software for FireWire File Exchange.
  5.  
  6.     Version:    1.0
  7.  
  8.     Written by:    Jay Lloyd
  9.  
  10.     Copyright:    © 1996-1999 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     File Ownership:
  13.  
  14.         DRI:                Jay Lloyd
  15.  
  16.         Other Contact:        
  17.  
  18.         Technology:            FireWire
  19.  
  20.     Writers:
  21.  
  22.         (jkl)    Jay Lloyd
  23.  
  24.     Change History (most recent first):
  25.  
  26.       <FW31>      4/8/99    jkl        Got rid of unused variable in DoDriverIO
  27.       <FW30>      4/8/99    jkl        Added DoDriverIO routine so fwix can fake being a GDF.
  28.       <FW29>      7/7/98    jkl        Deallocate node's data buffer address space when closing node.
  29.       <FW28>     1/15/98    jkl        Update for new headers.
  30.       <FW27>     5/28/97    jkl        Added a check for control packet index equal to 1 for a node
  31.                                     being restarted. Cleaned up some of the inUse and timing checks
  32.                                     added in last revision to investigate 5+ node problem.
  33.       <FW26>     5/27/97    jkl        Added a control packet indexing function to make sure control
  34.                                     packets are handled only once. Changed the flow control timer to
  35.                                     send flow control requests until a reply is received. This would
  36.                                     fix a case where a flow control request never got a reply.
  37.                                     Added more error checking and in use checking to investigate 5+
  38.                                     node problem.
  39.       <FW25>     5/15/97    jkl        Added a checksum routine around send data and data done. Added
  40.                                     an index to the flow control messages to only handle a reply
  41.                                     from the latest request. Put a check around sendpacket to make
  42.                                     sure it is not reentered.
  43.       <FW24>     2/27/97    jkl        Modified the WriteDataComplete routine to turn off flow control.
  44.                                     This will cause a flow control request and reply to be sent to
  45.                                     ensure the receive data buffer does not get overwritten with
  46.                                     more data before the receiver reads the existing data out of the
  47.                                     buffer. Reduced flow control retry time from 100 to 10 ms to
  48.                                     reduce transfer stalls.
  49.       <FW23>     2/21/97    ES        Added in use flags for all FWCommandObjects. Changed FWXClose to
  50.                                     wait for all of these flags to clear before doing any closing
  51.                                     activity. Removed wait on writePending. This fixes a hang on
  52.                                     closing bug.
  53.       <FW22>     2/21/97    EA        Added option to send diagnostic messages to FireBug.
  54.       <FW21>     2/21/97    jkl        Modified data transmissions to be sent to non-notify address
  55.                                     space.
  56.       <FW20>     2/20/97    ES        Changed FWClientAsynchRequestParams buffer field to
  57.                                     receiveBuffer.
  58.       <FW19>     2/19/97    jkl        Added a flow control send pending flag to make sure two messages
  59.                                     do not get sent at one time. Moved available buffer counts from
  60.                                     write completion routine to write routine.
  61.       <FW18>     2/14/97    jkl        Changed the flow control mechanism so the sender has to request
  62.                                     from the receiver how many packets he can send.
  63.       <FW17>     2/13/97    jkl        Added FlowControl packet counter to make sure flow control is
  64.                                     started properly.
  65.       <FW16>     2/13/97    jkl        Changed flow control to just keep up with number of data packets
  66.                                     available and sent. The flow control message is only sent when
  67.                                     all of the read packets have been received and are available,
  68.                                     thus the sender will stall after each number of sends. Changed
  69.                                     write notify routine to complete read data transaction when
  70.                                     requested data is equal to received data.
  71.       <FW15>     2/11/97    ES        Added closed boolean to FWXNodeData record. Added checks for
  72.                                     node being closed to prevent any writes going out or being
  73.                                     processed when we're closing a node connection. Changed write
  74.                                     queue deallocation to wait until no more writes are pending
  75.                                     before deallocating queue.
  76.       <FW14>     2/11/97    jkl        Added support for read control and data queues. Changed flow
  77.                                     control to a you can send me this much mechanism. Moved
  78.                                     FWXCommandComplete routine to the family.
  79.       <FW13>      2/2/97    jkl        Modified flow control time delay to check more often if it is ok
  80.                                     to write and write routine to handle writing buffers larger than
  81.                                     the allocated firewire buffer size.
  82.       <FW12>     1/27/97    ES        Changed FWXWrite to make sure there is still an item on the
  83.                                     write queue before processing the head of the queue (a race
  84.                                     condition was happening here). Changed FWXCloseNode to check if
  85.                                     the read and write queues were non-nil before deallocating.
  86.       <FW11>     1/16/97    ES        Changed FWXCreatePDriverUnitDirectory to set CSRROMEntryID's to
  87.                                     invalid before using them. Also, added code to deallocate entry
  88.                                     ID's.
  89.       <FW10>     1/16/97    jkl        Cleaned up read/write buffers on close.
  90.        <FW9>      1/8/97    ES        Changed to a FireWire protocol driver. Removed fixed FireWire
  91.                                     address allocation.
  92.        <FW8>    12/27/96    ES        Changed a bunch of "FWDriver"s to "FWClient"s.
  93.        <FW7>    12/16/96    ES        Changed to work with new read/write/lock request/complete
  94.                                     processing mechanism.
  95.        <FW6>     12/3/96    ES        Added kFWFixedAddress flag to FWAllocateAddressSpace.
  96.        <FW5>    11/13/96    jkl        Moved from DoDriverIO interface back to CallDriver. Added
  97.                                     multiple machine support. Added packet receive buffering.
  98.        <FW4>     10/31/96    jkl        Added flow control constants.
  99.        <FW3>     10/13/96    jkl        Added a basic flow control capability to turn off transmission
  100.                                        when the number of received buffers is low. All queue routines
  101.                                     are now the dsl queue routines. The ioMisc field in a parameter
  102.                                     block is now used to identify the packet type. For control
  103.                                     packets, the packet type is still also in the first long word
  104.                                     of the buffer. A sendpacket routine is now called by the write
  105.                                     handler and the write completion handler to send a packet. Fork
  106.                                     data is sent to a separate address space that is now set to write
  107.                                     notify.
  108.        <FW2>     10/3/96    jkl        Changed to use set driver interface calls rather than driver
  109.                                     interface table.
  110.        <FW1>     10/2/96    jkl        initial check-in, copied from avt driver
  111.                                        Added DoDriverIO interface.
  112.  
  113. */
  114.  
  115. #include <Types.h>
  116. #include <Errors.h>
  117. #include <Devices.h>
  118. #include <DriverServices.h>
  119. #include <FireWire.h>
  120.  
  121. #include "FWiX.h"
  122. #include "FWiXDriver.h"
  123.  
  124. #include <stdio.h>
  125. char  debugStr[256];
  126. static pascal void FWDebugStr(
  127.     ConstStr255Param            debuggerMsg)
  128. {
  129. #ifdef FW_DEBUG_BUILD
  130. #if FW_DEBUG_BUILD
  131.     DebugStr (debuggerMsg);
  132. #endif
  133. #endif
  134. }
  135.  
  136.  
  137. // define FireBug to enable sending diagnostic messages to FireBug on the fly.
  138. // WARNING:  Read the notes below first.  Be sure use "tcode on 1" in FireBug
  139. // so that you can see the messages.  [Also use "ack 0" if you don't want to
  140. // see many other packets]
  141.  
  142. //#define FireBug
  143. #ifdef FireBug
  144. static char fireBug[256];
  145. static FWReferenceID fireBugID;
  146. static FWCommandObjectID fireBugCommandObjectID;
  147. static UInt32 fireBugNeedCommandObject = 1;
  148.  
  149. static void FireBugMsg (char * msg)
  150. {
  151.     FWTopologyMap topology;
  152.     OSStatus status;
  153.     
  154.     if (fireBugNeedCommandObject) return;
  155.     
  156.     // It would probably be more safe to add a mechanism to make sure the
  157.     // most recent FireBugMsg completed before we recycle the command object.
  158.     // But I expect that the FWGetTopologyMap will probably take care of this.
  159.     
  160.     status = FWGetTopologyMap (fireBugID, &topology);
  161.     status = FWSetAsynchCommandGeneration (fireBugCommandObjectID, topology.generationNumber);
  162.     status = FWSetAsynchCommandBuffer (fireBugCommandObjectID, msg);
  163.     status = FWSetAsynchCommandLength (fireBugCommandObjectID, strlen (msg) + 1);
  164.     status = FWWrite (fireBugCommandObjectID);
  165. }
  166.  
  167. static void FireBugPrep (FWReferenceID tempID)
  168. {
  169.     OSStatus status;
  170.     
  171.     if (fireBugNeedCommandObject)
  172.     {
  173.         status = FWAllocateAsynchCommandObject (&fireBugCommandObjectID);
  174.         if (status == noErr)
  175.         {            
  176.             FWGetLocalFWReferenceIDFromFWReferenceID (tempID, &fireBugID);
  177.  
  178.             FWSetFWCommandParams(fireBugCommandObjectID, fireBugID, 0, nil, 0);
  179.             FWSetCommonAsynchCommandParams (fireBugCommandObjectID,
  180.                                             0x42420000, 0x00000000,
  181.                                             (Ptr) fireBug, sizeof (fireBug));
  182.             FWSetAsynchCommandMaxRetries (fireBugCommandObjectID, 0);
  183.             FWSetAsynchCommandMaxPayloadSize (fireBugCommandObjectID, 512);
  184.             FWSetAsynchCommandTransferFlags (fireBugCommandObjectID,
  185.                                              kFWAsynchAbsoluteAddress |
  186.                                              kFWAsynchOverrideMaxPayload);
  187.         }
  188.     
  189.         fireBugNeedCommandObject = 0;
  190.     }
  191. }
  192. #endif
  193.  
  194.  
  195. ////////////////////////////////////////////////////////////////////////////////
  196. //
  197. // Internal procedure prototypes.
  198. //
  199.  
  200. static void HandleFlowControlNotify (
  201.     FWXNodeDataPtr                pFWXNodeData,
  202.     Ptr                            pMessage);
  203.  
  204. static void HandleControlNotify (
  205.     FWXNodeDataPtr                pFWXNodeData,
  206.     Ptr                            pMessage,
  207.     UInt32                        msgLength);
  208.  
  209. static void HandleDataDone (
  210.     FWXNodeDataPtr                pFWXNodeData,
  211.     UInt32                        count,
  212.     UInt32                        checkSum);
  213.  
  214. static OSStatus    FWPDriverUnitAdded (
  215.     FWPDriverID                    fwPDriverID,
  216.     UInt32                        fwPDriverSpecificData,
  217.     FWUnitID                    fwUnitID);
  218.  
  219. static OSStatus    FWPDriverUnitRemoved (
  220.     FWPDriverID                    fwPDriverID,
  221.     UInt32                        fwPDriverSpecificData,
  222.     FWUnitID                    fwUnitID);
  223.  
  224. static void FlowControlComplete (
  225.     FWCommandObjectID            fwCommandObjectID,
  226.     OSStatus                    commandStatus,
  227.     UInt32                        completionProcData);
  228.  
  229. static void FlowControlReplyComplete (
  230.     FWCommandObjectID            fwCommandObjectID,
  231.     OSStatus                    commandStatus,
  232.     UInt32                        completionProcData);
  233.  
  234. static OSStatus FWXRead (
  235.     FWXAsynchParamsPtr            pFWXAsynchParams);
  236.  
  237. static OSStatus FWXWrite (
  238.     FWXAsynchParamsPtr            pFWXAsynchParams);
  239.  
  240. static void DataDoneComplete(
  241.     FWCommandObjectID            fwCommandObjectID,
  242.     OSStatus                    commandStatus,
  243.     UInt32                        completionProcData);
  244.  
  245. static void HandleWriteDataComplete(
  246.     FWCommandObjectID            fwCommandObjectID,
  247.     FWXNodeDataPtr                pFWXNodeData,
  248.     IOParamPtr                    pCompleteIOPb);
  249.  
  250. static void HandleWriteControlComplete(
  251.     FWCommandObjectID            fwCommandObjectID,
  252.     FWXNodeDataPtr                pFWXNodeData,
  253.     IOParamPtr                    pCompleteIOPb);
  254.  
  255. static void FWXWriteCompletion (
  256.     FWCommandObjectID            fwCommandObjectID,
  257.     OSStatus                    commandStatus,
  258.     UInt32                        completionProcData);
  259.  
  260. static OSStatus RetryFlowControl (
  261.     void                        *p1,
  262.     void                        *p2);
  263.  
  264. static OSStatus SendDataPacket(
  265.     FWXNodeDataPtr                pFWXNodeData,
  266.     IOParamPtr                    pb,
  267.     UInt32                        length);
  268.  
  269. static OSStatus SendControlPacket(
  270.     FWXNodeDataPtr                pFWXNodeData,
  271.     IOParamPtr                    pb,
  272.     UInt32                        length);
  273.  
  274. static OSStatus SendPacket (
  275.     FWXNodeDataPtr                pNodeData);
  276.     
  277. static OSStatus    FWXInitialize (
  278.     FWXInitializeParamsPtr        pFWXInitializeParams);
  279.  
  280. static OSStatus    FWXCreatePDriverUnitDirectory (
  281.     FWXDriverDataPtr            pFWXDriverData,
  282.     CSRROMEntryID                *pFWPDriverCSRROMUnitDirID);
  283.  
  284. static OSStatus    FWXTerminate (
  285.     FWXTerminateParamsPtr        pFWXTerminateParams);
  286.  
  287. static OSStatus FWXOpenNode (
  288.     FWXOpenNodeParamsPtr        pFWXInitializeParams);
  289.  
  290. static OSStatus FWXCloseNode (
  291.     FWXNodeDataPtr                pFWXNodeData);
  292.  
  293. static OSStatus SetupIOQueues (
  294.     FWXNodeDataPtr                pFWXNodeData);
  295.  
  296. static OSStatus FWXGetNodeDataFromNodeID (
  297.     FWXDriverDataPtr            pFWXDriverData,
  298.     UInt32                        generation,
  299.     UInt32                        nodeID,
  300.     FWXNodeDataPtr                *ppFWXNodeData);
  301.  
  302. ////////////////////////////////////////////////////////////////////////////////
  303. //
  304. // The driver descriptor.
  305. //
  306.  
  307. DriverDescription                 TheDriverDescription =
  308. {
  309.     kTheDescriptionSignature,
  310.     kInitialDriverDescriptor,
  311.     {
  312.         "\pFWiX",
  313.         1, 0, developStage, 1,
  314.     },
  315.     {
  316.         0                                        // driver runtime options
  317.         | (0 * kDriverIsLoadedUponDiscovery)
  318.         | (0 * kDriverIsOpenedUponLoad)
  319.         | (1 * kDriverIsUnderExpertControl)
  320.         | (1 * kDriverIsConcurrent)
  321.         | (1 * kDriverQueuesIOPB),
  322.         "\pFWiXDriver",
  323.     },
  324.  
  325.     1,
  326.     kServiceCategoryNdrvDriver,
  327.     kServiceCategoryFWiX,
  328. //    0,    // delete this
  329.     1,0,0,0
  330. };
  331.     
  332. FWPDriverDescription            ThePDriverDescription =
  333. {
  334.     kTheFWPDriverDescriptionSignature,
  335.     kInitialFWPDriverDescriptor,
  336.  
  337.     kServiceCategoryFWDriver,
  338.     0,0,developStage,0,
  339.  
  340.     0,
  341.     "\pFWiX"
  342. };
  343.  
  344.  
  345. ////////////////////////////////////////////////////////////////////////////////
  346. //
  347. // DoDriverIO
  348. //
  349. //   Main entry point.
  350. //
  351.  
  352. OSErr    DoDriverIO(
  353.     AddressSpaceID                addressSpaceID,
  354.     IOCommandID                    ioCommandID,
  355.     IOCommandContents            ioCommandContents,
  356.     IOCommandCode                ioCommandCode,
  357.     IOCommandKind                ioCommandKind)
  358. {
  359.     OSErr                        err = noErr;
  360.  
  361.     switch (ioCommandCode)
  362.     {
  363.         default:
  364.             err = noErr;
  365.     }
  366.  
  367.     // complete the command
  368.     if (ioCommandKind == kImmediateIOCommandKind)
  369.         return err;
  370.     else
  371.         return IOCommandIsComplete(ioCommandID, err);
  372.  
  373.     return err;
  374. }
  375.  
  376.  
  377. ////////////////////////////////////////////////////////////////////////////////
  378. //
  379. //    FWClientWriteRequestInterface
  380. //
  381. //    Handle writes to the client. Check the type of received data by address
  382. //    space id. Set flow control information. If the data is control information
  383. //    send any file data information to the application then send the control
  384. //    information. If the data is file data add it to the receive buffer, if it
  385. //    overflows the receive buffer, send the buffer to the app and get a new one.
  386. //
  387.  
  388. OSStatus FWClientWriteCompleteInterface(
  389.     FWClientAsynchRequestParamsPtr
  390.                                 pFWClientAsynchRequestParams,
  391.     UInt32                        *pCommandAcceptance)
  392. {
  393.     FWXDriverDataPtr            pFWXDriverData;
  394.     FWXNodeDataPtr                pFWXNodeData;
  395.     OSStatus                    status = noErr;
  396.  
  397.     // recover our node data
  398.     //zzz check status
  399.     pFWXDriverData = (FWXDriverDataPtr) pFWClientAsynchRequestParams->pAddressSpecificData;
  400.     status = FWXGetNodeDataFromNodeID (pFWXDriverData,
  401.                                        pFWClientAsynchRequestParams->generation,
  402.                                        pFWClientAsynchRequestParams->sourceID,
  403.                                        &pFWXNodeData);
  404.  
  405.     if (status == noErr)
  406.     {
  407.         if (pFWClientAsynchRequestParams->fwAddressSpaceID == pFWXDriverData->fcAddressSpaceID)
  408.             
  409.             HandleFlowControlNotify (pFWXNodeData,
  410.                                      pFWClientAsynchRequestParams->receiveBuffer);
  411.                                      
  412.         else if (pFWClientAsynchRequestParams->fwAddressSpaceID == pFWXDriverData->controlAddressSpaceID)
  413.             
  414.             HandleControlNotify (pFWXNodeData,
  415.                                  pFWClientAsynchRequestParams->receiveBuffer,
  416.                                  pFWClientAsynchRequestParams->length);
  417.     }
  418.  
  419.     // Complete FireWire client command.
  420.     FWClientCommandIsComplete
  421.         (pFWClientAsynchRequestParams->fwClientInterfaceParams.fwClientCommandID,
  422.          status);
  423.  
  424.     // Return command acceptance.
  425.     //zzz is this the right way?  If we've completed the command, we can accept more.
  426.     *pCommandAcceptance = kFWClientCommandAcceptNoMore;
  427.  
  428.     return status;
  429. }
  430.  
  431. ////////////////////////////////////////////////////////////////////////////////
  432. //
  433. // HandleFlowControlNotify
  434. //
  435. //    Handle notification of a flow control message received. If the message
  436. //    is a request, reply with the appropriate flow control value. If the
  437. //    message is a reply and there are now receive buffers available, try
  438. //    sending a packet. If there are no buffers available start a timer to
  439. //    wait and then send another flow control request.
  440. //
  441.  
  442. static void HandleFlowControlNotify (
  443.     FWXNodeDataPtr            pFWXNodeData,
  444.     Ptr                        pMessage)
  445. {
  446.     UInt32                    fcPacketCount;
  447.     UInt32                    messageType;
  448.     AbsoluteTime            fcRequestDelay;
  449.     OSStatus                status = noErr;
  450.     
  451.     messageType = ((UInt32 *) pMessage)[0];
  452.     switch (messageType)
  453.     {
  454.         case kFCDataRequest:
  455.             if (!pFWXNodeData->fcReplyCommandObjectInUse)
  456.             {
  457.                 pFWXNodeData->fcReplyBuffer[0] = kFCDataReply;
  458.                 pFWXNodeData->fcReplyBuffer[1] = pFWXNodeData->dataPbCount;
  459.                 pFWXNodeData->fcReplyBuffer[2] = ((UInt32 *) pMessage)[2];
  460.                 pFWXNodeData->fcReplyCommandObjectInUse = true;
  461.                 FWSetFWCommandCompletionProcData (pFWXNodeData->fcReplyCommandObjectID, (UInt32) pFWXNodeData);
  462.                 FWSetCommonAsynchCommandParams (pFWXNodeData->fcReplyCommandObjectID,
  463.                                                 pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  464.                                                 pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  465.                                                 (Ptr) pFWXNodeData->fcReplyBuffer,
  466.                                                 kFlowControlSize);
  467.                 status = FWWrite(pFWXNodeData->fcReplyCommandObjectID);
  468.                 if (status != noErr)
  469.                     pFWXNodeData->fcReplyCommandObjectInUse = false;                    
  470.             }
  471.             break;
  472.         
  473.         case kFCControlRequest:
  474.             if (!pFWXNodeData->fcReplyCommandObjectInUse)
  475.             {
  476.                 pFWXNodeData->fcReplyBuffer[0] = kFCControlReply;
  477.                 pFWXNodeData->fcReplyBuffer[1] = pFWXNodeData->controlPbCount;
  478.                 pFWXNodeData->fcReplyBuffer[2] = ((UInt32 *) pMessage)[2];
  479.                 pFWXNodeData->fcReplyCommandObjectInUse = true;
  480.                 FWSetFWCommandCompletionProcData (pFWXNodeData->fcReplyCommandObjectID, (UInt32) pFWXNodeData);
  481.                 FWSetCommonAsynchCommandParams (pFWXNodeData->fcReplyCommandObjectID,
  482.                                                 pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  483.                                                 pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  484.                                                 (Ptr) pFWXNodeData->fcReplyBuffer,
  485.                                                 kFlowControlSize);
  486.                 status = FWWrite(pFWXNodeData->fcReplyCommandObjectID);
  487.                 if (status != noErr)
  488.                     pFWXNodeData->fcReplyCommandObjectInUse = false;                    
  489.             }
  490.             break;
  491.         
  492.         case kFCDataReply:
  493.             fcPacketCount = ((UInt32 *) pMessage)[2];
  494.             CancelTimer(pFWXNodeData->fcTimerID, &fcRequestDelay);
  495.             if (fcPacketCount == pFWXNodeData->fcIndex)
  496.             {
  497.                 pFWXNodeData->fcIndex++;
  498.                 pFWXNodeData->dataPbAvail = ((SInt32 *) pMessage)[1];
  499.                 if (pFWXNodeData->dataPbAvail > 0)
  500.                 {
  501.                     if (pFWXNodeData->fcStopSend)
  502.                     {
  503.                         // there were no buffers before, now there are some, restart sending
  504.                         pFWXNodeData->fcStopSend = false;
  505.                         status = SendPacket(pFWXNodeData);
  506.                     }
  507.                 }
  508.                 else
  509.                 {
  510.                     // still no buffers available, reset timer
  511.                     fcRequestDelay = AddAbsoluteToAbsolute (UpTime (), DurationToAbsolute(20));        // 20 milliseconds
  512.                 status = SetInterruptTimer (&fcRequestDelay,                                    // JKL *** what's a good delay
  513.                                             RetryFlowControl,
  514.                                             (void *) pFWXNodeData,
  515.                                             &pFWXNodeData->fcTimerID);
  516.             }
  517.             }
  518.             else
  519.             {
  520.                 // received flow control message out of order, retry
  521.                 fcRequestDelay = AddAbsoluteToAbsolute (UpTime (), DurationToAbsolute(20));        // 20 milliseconds
  522.                 status = SetInterruptTimer (&fcRequestDelay,                                    // JKL *** what's a good delay
  523.                                             RetryFlowControl,
  524.                                             (void *) pFWXNodeData,
  525.                                             &pFWXNodeData->fcTimerID);
  526.             }
  527.             break;
  528.         
  529.         case kFCControlReply:
  530.             fcPacketCount = ((UInt32 *) pMessage)[2];
  531.             CancelTimer(pFWXNodeData->fcTimerID, &fcRequestDelay);
  532.             if (fcPacketCount == pFWXNodeData->fcIndex)
  533.             {
  534.                 pFWXNodeData->fcIndex++;
  535.                 pFWXNodeData->controlPbAvail = ((SInt32 *) pMessage)[1];
  536.                 if (pFWXNodeData->controlPbAvail > 0)
  537.                 {
  538.                     if (pFWXNodeData->fcStopSend)
  539.                     {
  540.                         pFWXNodeData->fcStopSend = false;
  541.                         status = SendPacket(pFWXNodeData);
  542.                     }
  543.                 }
  544.                 else
  545.                 {
  546.                     // still no buffers available, reset timer
  547.                     fcRequestDelay = AddAbsoluteToAbsolute (UpTime (), DurationToAbsolute(20));        // 20 milliseconds
  548.                     status = SetInterruptTimer (&fcRequestDelay,                                    // JKL *** what's a good delay
  549.                                                 RetryFlowControl,
  550.                                                 (void *) pFWXNodeData,
  551.                                                 &pFWXNodeData->fcTimerID);
  552.                 }
  553.             }
  554.             else
  555.             {
  556.                 fcRequestDelay = AddAbsoluteToAbsolute (UpTime (), DurationToAbsolute(20));        // 10 milliseconds
  557.                 status = SetInterruptTimer (&fcRequestDelay,                                    // JKL *** what's a good delay
  558.                                             RetryFlowControl,
  559.                                             (void *) pFWXNodeData,
  560.                                             &pFWXNodeData->fcTimerID);
  561.             }
  562.             break;
  563.         
  564.         case kAddressInfoRequest:
  565.             if (!pFWXNodeData->fcReplyCommandObjectInUse)
  566.             {
  567.             pFWXNodeData->remoteDataAddress.addressHi = ((UInt32 *) pMessage)[1];
  568.             pFWXNodeData->remoteDataAddress.addressLo = ((UInt32 *) pMessage)[2];
  569.             pFWXNodeData->fcReplyBuffer[0] = kAddressInfoReply;
  570.             pFWXNodeData->fcReplyBuffer[1] = pFWXNodeData->localDataAddress.addressHi;
  571.             pFWXNodeData->fcReplyBuffer[2] = pFWXNodeData->localDataAddress.addressLo;
  572.             pFWXNodeData->fcReplyCommandObjectInUse = true;
  573.             FWSetFWCommandCompletionProcData (pFWXNodeData->fcReplyCommandObjectID, (UInt32) pFWXNodeData);
  574.             FWSetCommonAsynchCommandParams (pFWXNodeData->fcReplyCommandObjectID,
  575.                                             pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  576.                                             pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  577.                                             (Ptr) pFWXNodeData->fcReplyBuffer,
  578.                                             kFlowControlSize);
  579.             status = FWWrite(pFWXNodeData->fcReplyCommandObjectID);
  580.                 if (status != noErr)
  581.                     pFWXNodeData->fcReplyCommandObjectInUse = false;                    
  582.             }
  583.             else
  584.             {
  585.                 FWDebugStr("\paddress info request, object in use");
  586.             }
  587.             break;
  588.             
  589.         case kAddressInfoReply:
  590.             pFWXNodeData->remoteDataAddress.addressHi = ((UInt32 *) pMessage)[1];
  591.             pFWXNodeData->remoteDataAddress.addressLo = ((UInt32 *) pMessage)[2];
  592.             break;
  593.             
  594.         default:
  595.             sprintf(debugStr,"fcNotify, message type unknown: %d", messageType);
  596.             FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  597.             break;
  598.     }
  599.         
  600.     if (status != noErr)
  601.     {
  602.         sprintf(debugStr,"fcNotify, error in FWWrite: %d", status);
  603.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  604.     }
  605. }
  606.  
  607. ////////////////////////////////////////////////////////////////////////////////
  608. //
  609. // HandleControlNotify
  610. //
  611. //    Handle notification of a control message received. If the message is data
  612. //    done, complete the data request, else complete the control request.
  613. //
  614.  
  615. static void HandleControlNotify (
  616.     FWXNodeDataPtr                pFWXNodeData,
  617.     Ptr                            pMessage,
  618.     UInt32                        msgLength)
  619. {
  620.     IOParamPtr                    pb;
  621.     UInt32                        packetType;
  622.     UInt32                        packetIndex;
  623.     OSStatus                    status = noErr;
  624.  
  625.     
  626.     packetIndex = ((UInt32 *) pMessage)[0];
  627.     if ((packetIndex > pFWXNodeData->lastIndex) || (packetIndex == 1))    // will be one if fwix is closed
  628.     {                                                                    // and opened on other machine
  629.         pFWXNodeData->lastIndex = packetIndex;
  630.         packetType = ((UInt32 *) pMessage)[1];
  631.     
  632.         if (packetType == kDataDone)
  633.         {
  634.                 HandleDataDone(pFWXNodeData, ((UInt32 *) pMessage)[2], ((UInt32 *) pMessage)[3]);
  635.         }
  636.         else
  637.         {        
  638.             // handle control packet
  639.             pb = (IOParamPtr) pFWXNodeData->pReadControlQHdr->qHead;
  640.             if (pb != nil)
  641.             {
  642.                 pFWXNodeData->controlPbCount--;
  643.                 if (pFWXNodeData->controlPbCount < 0)
  644.                     FWDebugStr("\pcontrol buffer count < 0, ControlNotify");
  645.                 PBDequeueFirst(pFWXNodeData->pReadControlQHdr, (QElemPtr *) &pb);
  646.                 BlockMoveData(pMessage, pb->ioBuffer, msgLength);
  647.                 pb->ioActCount = msgLength;
  648.                 pb->ioMisc = (Ptr) packetType;
  649.                 FWXCommandIsComplete(pb, status);
  650.             }
  651.             else
  652.             {
  653.                 FWDebugStr("\pNo receive control buffer, WriteNotify");
  654.             }
  655.         }
  656.     }
  657.     else
  658.     {
  659.         sprintf(debugStr,"echo packet, last: %ld, received: %ld", pFWXNodeData->lastIndex, packetIndex);
  660.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  661.     }
  662. }
  663.     
  664. ////////////////////////////////////////////////////////////////////////////////
  665. //
  666. // HandleDataDone
  667. //
  668. //    Handle notification of a data done message. If the data completes the
  669. //    request, send the packet to the app. If the data overflows the request, send
  670. //    the current packet to the app and start a new one. Otherwise just copy the data
  671. //    into the current packet.
  672. //
  673.  
  674. static void HandleDataDone (
  675.     FWXNodeDataPtr                pFWXNodeData,
  676.     UInt32                        count,
  677.     UInt32                        checkSum)
  678. {
  679.     IOParamPtr                    pb;
  680.     UInt32                        byteCount;
  681.     UInt32                        dataSum;
  682.     OSStatus                    status = noErr;
  683.  
  684.     pb = (IOParamPtr) pFWXNodeData->pReadDataQHdr->qHead;    
  685.     if (pb != nil)
  686.     {
  687.         dataSum = 0;
  688.         for (byteCount = 0; byteCount < count; ++byteCount)
  689.             dataSum += (pFWXNodeData->dataBuffer)[byteCount];
  690.         
  691.         if (dataSum != checkSum)
  692.         {
  693.             status = badCksmErr;
  694.             sprintf(debugStr,"Checksum error, expected: %ld, received: %ld", checkSum, dataSum);
  695.             FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  696.         }
  697.         
  698.         BlockMoveData (pFWXNodeData->dataBuffer,
  699.                        pb->ioBuffer + pb->ioActCount,
  700.                        count);
  701.         pb->ioActCount += count;
  702.  
  703.         pFWXNodeData->dataPbCount--;
  704.         if (pFWXNodeData->dataPbCount < 0)
  705.             FWDebugStr("\pdataPbCount < 0, data done");
  706.  
  707.             PBDequeueFirst(pFWXNodeData->pReadDataQHdr, (QElemPtr *) &pb);
  708.             pb->ioMisc = (Ptr) kForkData;
  709.             FWXCommandIsComplete(pb, status);
  710.         }
  711.     else
  712.         FWDebugStr("\pNo receive buffer for data, data done");
  713. }
  714.  
  715.  
  716. ////////////////////////////////////////////////////////////////////////////////
  717. //
  718. // FWPDriverUnitAdded
  719. //
  720. //   FireWire protocol driver interface for handling added units.
  721. //
  722.  
  723. static OSStatus    FWPDriverUnitAdded(
  724.     FWPDriverID                    fwPDriverID,
  725.     UInt32                        fwPDriverSpecificData,
  726.     FWUnitID                    fwUnitID)
  727. {
  728.     FWXDriverDataPtr            pFWXDriverData;
  729.     OSStatus                    status = noErr;
  730.  
  731.     // Get our driver data.
  732.     pFWXDriverData = (FWXDriverDataPtr) fwPDriverSpecificData;
  733.  
  734.     status = RegisterFWXNode (pFWXDriverData->fwxDriverID, (UInt32) fwUnitID);
  735.  
  736.     return (status);
  737. }
  738.  
  739. ////////////////////////////////////////////////////////////////////////////////
  740. //
  741. // FWPDriverUnitRemoved
  742. //
  743. //   FireWire protocol driver interface for handling removed units.
  744. //
  745.  
  746. static OSStatus    FWPDriverUnitRemoved(
  747.     FWPDriverID                    fwPDriverID,
  748.     UInt32                        fwPDriverSpecificData,
  749.     FWUnitID                    fwUnitID)
  750. {
  751.     FWXDriverDataPtr            pFWXDriverData;
  752.     OSStatus                    status = noErr;
  753.  
  754.     // Get our driver data.
  755.     pFWXDriverData = (FWXDriverDataPtr) fwPDriverSpecificData;
  756.  
  757.     status = UnregisterFWXNode (pFWXDriverData->fwxDriverID, (UInt32) fwUnitID);
  758.  
  759.     return (status);
  760. }
  761.  
  762.  
  763. ////////////////////////////////////////////////////////////////////////////////
  764. //
  765. //    FlowControlCompletion
  766. //
  767. //    Completion routine for flow control message write
  768. //
  769.  
  770. static void FlowControlComplete(
  771.     FWCommandObjectID            fwCommandObjectID,
  772.     OSStatus                    commandStatus,
  773.     UInt32                        completionProcData)
  774. {
  775.     FWXNodeDataPtr            pFWXNodeData;
  776.  
  777.     pFWXNodeData = (FWXNodeDataPtr) completionProcData;
  778.     pFWXNodeData->fcSendCommandObjectInUse = false;
  779.     if (commandStatus != noErr)
  780.     {
  781.         if ((commandStatus == timeoutErr) ||
  782.             (commandStatus == retryExceededErr) ||
  783.             (commandStatus == busReconfiguredErr))
  784.         {
  785.             pFWXNodeData->fcSendCommandObjectInUse = true;
  786.             commandStatus = FWWrite(fwCommandObjectID);
  787.             if (commandStatus != noErr)
  788.                 pFWXNodeData->fcSendCommandObjectInUse = false;
  789.         }
  790.         else
  791.         {
  792.         sprintf(debugStr,"Error in send flow control: %ld", commandStatus);
  793.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  794.     }
  795.     }
  796. }
  797.  
  798.  
  799. ////////////////////////////////////////////////////////////////////////////////
  800. //
  801. //    FlowControlReplyComplete
  802. //
  803. //    Completion routine for flow control reply write
  804. //
  805.  
  806. static void FlowControlReplyComplete(
  807.     FWCommandObjectID            fwCommandObjectID,
  808.     OSStatus                    commandStatus,
  809.     UInt32                        completionProcData)
  810. {
  811.     FWXNodeDataPtr            pFWXNodeData;
  812.  
  813.     pFWXNodeData = (FWXNodeDataPtr) completionProcData;
  814.     pFWXNodeData->fcReplyCommandObjectInUse = false;
  815.     if (commandStatus != noErr)
  816.     {
  817.         if ((commandStatus == timeoutErr) ||
  818.             (commandStatus == retryExceededErr) ||
  819.             (commandStatus == busReconfiguredErr))
  820.         {
  821.             commandStatus = FWWrite(fwCommandObjectID);
  822.             if (commandStatus != noErr)
  823.                 pFWXNodeData->fcReplyCommandObjectInUse = false;
  824.         }
  825.         else
  826.         {
  827.         sprintf(debugStr,"Error in send flow control: %ld", commandStatus);
  828.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  829.     }
  830.     }
  831. }
  832.  
  833.  
  834. ////////////////////////////////////////////////////////////////////////////////
  835. //
  836. //    FWXRead
  837. //
  838. //    FWiX read routine. This is not a FireWire read routine. This is an
  839. //    interface for the FwiX application to pass read buffers to the
  840. //    driver to handle received data.
  841. //
  842. //    Queue the application parameter    blocks. The FWClientWriteCompleteInterface
  843. //    routine handles the rest. A counter keeps the number of read control parameter
  844. //    blocks which will tell the sender how many control commands it can send.
  845. //    Also keep up with the size of the data buffer to tell the sender how much
  846. //    data can be sent.
  847. //
  848.  
  849. static OSStatus FWXRead(
  850.     FWXAsynchParamsPtr        pFWXAsynchParams)
  851. {
  852.     FWXNodeDataPtr            pFWXNodeData;
  853.     IOParamPtr                pIOParam;
  854.     OSStatus                status = noErr;
  855.  
  856.     pFWXNodeData = (FWXNodeDataPtr) pFWXAsynchParams->fwxInterfaceParams.pNodeSpecificData;
  857.     pIOParam = pFWXAsynchParams->pIOPB;
  858.     
  859.     pIOParam->ioActCount = 0;
  860.     if (pIOParam->ioMisc == (Ptr) kForkData)
  861.     {
  862.         status = PBEnqueueLast((QElemPtr) pIOParam, pFWXNodeData->pReadDataQHdr);
  863.         pFWXNodeData->dataPbCount++;
  864.         if (pFWXNodeData->dataPbCount > 6)        // value from fwixmain.h
  865.             FWDebugStr("\pdata buffer count too high, FWXRead");
  866.     }
  867.     else
  868.     {
  869.         status = PBEnqueueLast((QElemPtr) pIOParam, pFWXNodeData->pReadControlQHdr);
  870.         pFWXNodeData->controlPbCount++;
  871.         if (pFWXNodeData->dataPbCount > 20)        // value from fwixmain.h
  872.             FWDebugStr("\pcontrol buffer count too high, FWXRead");
  873.     }
  874.         
  875.     return status;
  876. }
  877.  
  878.  
  879. ////////////////////////////////////////////////////////////////////////////////
  880. //
  881. //    FWXWrite
  882. //
  883. //    Queue the write request. If there are no writes in progress, go ahead and
  884. //    issue a write. Otherwise the queued write request will be picked up by
  885. //    the write completion routine.
  886. //
  887.  
  888. static OSStatus FWXWrite(
  889.     FWXAsynchParamsPtr        pFWXAsynchParams)
  890. {
  891.     FWXNodeDataPtr            pFWXNodeData;
  892.     IOParamPtr                pIOParam;
  893.     OSStatus                status = noErr;
  894.  
  895.     // recover driver data
  896.     pFWXNodeData = (FWXNodeDataPtr) pFWXAsynchParams->fwxInterfaceParams.pNodeSpecificData;
  897.     pIOParam = pFWXAsynchParams->pIOPB;
  898.  
  899.     // queue the parameter block
  900.     pIOParam->ioActCount = 0;
  901.     PBEnqueueLast((QElemPtr) pIOParam, pFWXNodeData->pWriteQHdr);
  902.     
  903.     if (!pFWXNodeData->writePending)
  904.     {    
  905.         pIOParam = (IOParamPtr) pFWXNodeData->pWriteQHdr->qHead;
  906.         if (pIOParam != nil)
  907.         {
  908.             pFWXNodeData->writePending = true;    
  909.             pFWXNodeData->pCurIOParam = pIOParam;
  910.             status = SendPacket(pFWXNodeData);
  911.         }
  912.     }
  913.     return status;
  914. }
  915.  
  916.  
  917. ////////////////////////////////////////////////////////////////////////////////
  918. //
  919. //    DataDoneComplete
  920. //
  921. //    Data done complete routine. Set completion routine back to write complete
  922. //    for asynchCommandObject. Try sending another packet.
  923. //
  924.  
  925. static void DataDoneComplete(
  926.     FWCommandObjectID            fwCommandObjectID,
  927.     OSStatus                    commandStatus,
  928.     UInt32                        completionProcData)
  929. {
  930.     FWXNodeDataPtr                pFWXNodeData;
  931.     IOParamPtr                    pb;
  932.  
  933.     // recover node data
  934.     pFWXNodeData = (FWXNodeDataPtr) completionProcData;
  935.  
  936.     // make sure node connection is still open
  937.     if (pFWXNodeData->closed)
  938.         commandStatus = notOpenErr;
  939.  
  940.     if (commandStatus == noErr)
  941.     {
  942.         FWSetFWCommandCompletionProc (fwCommandObjectID, FWXWriteCompletion);
  943.         pFWXNodeData->writeAsynchCommandObjectInUse = false;
  944.  
  945.         // check the queue for more parameter blocks to send
  946.         pb = (IOParamPtr) pFWXNodeData->pWriteQHdr->qHead;
  947.         pFWXNodeData->pCurIOParam = pb;
  948.         if (pb != nil)
  949.             SendPacket(pFWXNodeData);
  950.         else
  951.             pFWXNodeData->writePending = false;
  952.     }
  953.     else if ((commandStatus == timeoutErr) ||
  954.             (commandStatus == retryExceededErr) ||
  955.             (commandStatus == busReconfiguredErr))
  956.     {
  957.         // try sending again
  958.         commandStatus = FWWrite(fwCommandObjectID);
  959.         if (commandStatus != noErr)
  960.             pFWXNodeData->writeAsynchCommandObjectInUse = false;
  961.     }
  962.     else
  963.     {
  964.         pFWXNodeData->writeAsynchCommandObjectInUse = false;
  965.         sprintf(debugStr, "Error in data done complete: %ld", commandStatus);
  966.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  967.     }
  968. }
  969.  
  970. ////////////////////////////////////////////////////////////////////////////////
  971. //
  972. //    HandleWriteDataComplete
  973. //
  974. //    Write data completion routine. If all of the requested data in the
  975. //    current parameter block has been sent, complete the command then
  976. //    dequeue another request and start sending it. If there are no requests
  977. //    waiting, set write complete to true and the next write request will restart
  978. //    the write/write complete loop.
  979. //
  980.  
  981. static void HandleWriteDataComplete(
  982.     FWCommandObjectID            fwCommandObjectID,
  983.     FWXNodeDataPtr                pFWXNodeData,
  984.     IOParamPtr                    pCompleteIOPb)
  985. {
  986.     IOParamPtr                    doneIOParam;
  987.     Ptr                            dataSent;
  988.     UInt32                        dataSum;
  989.     UInt32                        actCount;
  990.     UInt32                        byteCount;
  991.     OSStatus                    status;
  992.  
  993.     FWGetAsynchCommandBytesTransferred(fwCommandObjectID, &actCount);
  994.     pCompleteIOPb->ioActCount += actCount;
  995.     pFWXNodeData->dataPbAvail = 0;            // turn off flow control to allow for time
  996.                                             // for receiver to read data out of buffer
  997.     
  998.     pFWXNodeData->writeAsynchCommandObjectInUse    = false;
  999.     
  1000.     FWGetAsynchCommandBuffer(fwCommandObjectID, &dataSent);
  1001.     dataSum = 0;
  1002.     for (byteCount = 0; byteCount < actCount; ++byteCount)
  1003.         dataSum += dataSent[byteCount];
  1004.     
  1005.     pFWXNodeData->controlIndex++;
  1006.     pFWXNodeData->dataDoneBuffer[0] = pFWXNodeData->controlIndex;
  1007.  
  1008.     // set packet type, data sent length, checksum
  1009.     pFWXNodeData->dataDoneBuffer[1] = kDataDone;
  1010.     pFWXNodeData->dataDoneBuffer[2] = actCount;
  1011.     pFWXNodeData->dataDoneBuffer[3] = dataSum;
  1012.  
  1013.     if (!pFWXNodeData->writeAsynchCommandObjectInUse)
  1014.     {
  1015.     pFWXNodeData->writeAsynchCommandObjectInUse = true;
  1016.     FWSetFWCommandCompletionProcData (fwCommandObjectID, (UInt32) pFWXNodeData);
  1017.     FWSetCommonAsynchCommandParams (fwCommandObjectID,
  1018.                                     pFWXNodeData->fwxUnitInfo.controlAddress.addressHi,
  1019.                                     pFWXNodeData->fwxUnitInfo.controlAddress.addressLo,
  1020.                                     (Ptr) pFWXNodeData->dataDoneBuffer,
  1021.                                     kDataDoneBufSize);
  1022.     FWSetFWCommandCompletionProc (fwCommandObjectID, DataDoneComplete);
  1023.     
  1024.         // send the data done notification after dequeuing the packet
  1025.         status = FWWrite(pFWXNodeData->writeAsynchCommandObjectID);
  1026.         if (status != noErr)
  1027.             pFWXNodeData->writeAsynchCommandObjectInUse = false;
  1028.         
  1029.     // if all of the requested data was not sent, send some more
  1030.     if (pCompleteIOPb->ioActCount < pCompleteIOPb->ioReqCount)
  1031.     {
  1032.         FWDebugStr("\pwrite data complete, should not be here");
  1033.         SendPacket(pFWXNodeData);
  1034.     }
  1035.     else
  1036.     {
  1037.         // completed sending this parameter block, dequeue it and complete
  1038.         PBDequeueFirst(pFWXNodeData->pWriteQHdr, (QElemPtr *) &doneIOParam);
  1039.         if (doneIOParam->ioCmdAddr != pCompleteIOPb->ioCmdAddr)
  1040.             FWDebugStr("\pWrite completion, queued pb not the same as completed pb");
  1041.         pFWXNodeData->pCurIOParam = nil;
  1042.         FWXCommandIsComplete(doneIOParam, noErr);
  1043.     }
  1044.     
  1045.     }
  1046.     else
  1047.         FWDebugStr("\pWriteDataComplete, writeAsynchCommandObjectInUse");
  1048. }
  1049.  
  1050. ////////////////////////////////////////////////////////////////////////////////
  1051. //
  1052. //    HandleWriteControlComplete
  1053. //
  1054. //    Write control completion routine. Complete the command then
  1055. //    dequeue another request and start sending it. If there are no requests
  1056. //    waiting, set write complete to true and the next write request will restart
  1057. //    the write/write complete loop.
  1058. //
  1059.  
  1060. static void HandleWriteControlComplete(
  1061.     FWCommandObjectID            fwCommandObjectID,
  1062.     FWXNodeDataPtr                pFWXNodeData,
  1063.     IOParamPtr                    pCompleteIOPb)
  1064. {
  1065.     IOParamPtr                    doneIOParam;
  1066.     UInt32                        actCount;            // count of bytes transferred
  1067.     OSErr                        err;
  1068.  
  1069.     FWGetAsynchCommandBytesTransferred(fwCommandObjectID, &actCount);
  1070.     pCompleteIOPb->ioActCount += actCount;
  1071.     
  1072.     // completed sending this parameter block, dequeue it and complete
  1073.     err = PBDequeueFirst(pFWXNodeData->pWriteQHdr, (QElemPtr *) &doneIOParam);
  1074.     if (doneIOParam->ioCmdAddr != pCompleteIOPb->ioCmdAddr)
  1075.         FWDebugStr("\pWriteControlComplete, queued pb not the same as completed pb");
  1076.  
  1077.     FWXCommandIsComplete(doneIOParam, noErr);
  1078.     pFWXNodeData->writeAsynchCommandObjectInUse = false;
  1079.     
  1080.     // check the queue for more parameter blocks to send
  1081.     pCompleteIOPb = (IOParamPtr) pFWXNodeData->pWriteQHdr->qHead;
  1082.     pFWXNodeData->pCurIOParam = pCompleteIOPb;
  1083.     if (pCompleteIOPb != nil)
  1084.         SendPacket(pFWXNodeData);
  1085.     else
  1086.         pFWXNodeData->writePending = false;
  1087. }
  1088.  
  1089. ////////////////////////////////////////////////////////////////////////////////
  1090. //
  1091. //    FWXWriteCompletion
  1092. //
  1093. //    FWiX write completion routine. If all of the requested data in the
  1094. //    current parameter block has been sent, complete the command then
  1095. //    dequeue another request and start sending it. If there are no requests
  1096. //    waiting, set write complete to true and the next write request will restart
  1097. //    the write/write complete loop.
  1098. //
  1099.  
  1100. static void FWXWriteCompletion(
  1101.     FWCommandObjectID            fwCommandObjectID,
  1102.     OSStatus                    commandStatus,
  1103.     UInt32                        completionProcData)
  1104. {
  1105.     FWXNodeDataPtr                pFWXNodeData;
  1106.     IOParamPtr                    pIOParam;            // param block being processed
  1107.     IOParamPtr                    doneIOParam;        // param block being processed
  1108.  
  1109.     // recover original parameter block 
  1110.     pFWXNodeData = (FWXNodeDataPtr) completionProcData;
  1111.     pIOParam = pFWXNodeData->pCurIOParam;
  1112.  
  1113.     // make sure node connection is still open
  1114.     if (pFWXNodeData->closed)
  1115.         commandStatus = notOpenErr;
  1116.  
  1117.     // check transfer stats and increment actual bytes transferred
  1118.     if (commandStatus == noErr)
  1119.     {
  1120.         if (pIOParam->ioMisc == (Ptr) kForkData)
  1121.             HandleWriteDataComplete(fwCommandObjectID, pFWXNodeData, pIOParam);
  1122.         else
  1123.             HandleWriteControlComplete(fwCommandObjectID, pFWXNodeData, pIOParam);
  1124.     }
  1125.     else if ((commandStatus == timeoutErr) ||
  1126.             (commandStatus == retryExceededErr) ||
  1127.             (commandStatus == busReconfiguredErr))
  1128.     {
  1129.         // got a timeout error, try sending again
  1130.         //sprintf(debugStr, "Timeout error in WriteCompletion, pb: %lx", pIOParam);
  1131.         //FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  1132.         SendPacket(pFWXNodeData);
  1133.     }
  1134.     else
  1135.     {
  1136.         // completion routine got an error
  1137.         sprintf(debugStr,"Error in write complete: %ld", commandStatus);
  1138.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  1139.  
  1140.         pFWXNodeData->writeAsynchCommandObjectInUse = false;
  1141.         PBDequeueFirst(pFWXNodeData->pWriteQHdr, (QElemPtr *) &doneIOParam);
  1142.         pFWXNodeData->writePending = false;
  1143.         FWXCommandIsComplete(doneIOParam, commandStatus);
  1144.     }
  1145. }
  1146.  
  1147. ////////////////////////////////////////////////////////////////////////////////
  1148. //
  1149. //    RetryFlowControl
  1150. //
  1151. //    Timer-based routine to request if transmit continue. Check to see if
  1152. //    data transmit or control transmit is held and send appropriate request.
  1153. //
  1154. // JKL *** can another flow control write be pending? What if there is no
  1155. //    response?
  1156. //
  1157.  
  1158. static OSStatus RetryFlowControl(
  1159.     void                *p1,        // node data
  1160.     void                *p2)
  1161. {
  1162.     FWXNodeDataPtr        pFWXNodeData;
  1163.     IOParamPtr            pb;
  1164.     OSStatus            status = noErr;
  1165.     
  1166.     pFWXNodeData = (FWXNodeDataPtr) p1;
  1167.     pb = pFWXNodeData->pCurIOParam;
  1168.  
  1169.     // make sure node connection is still open
  1170.     if (pFWXNodeData->closed)
  1171.         status = notOpenErr;
  1172.  
  1173.     if ((status == noErr) && (!pFWXNodeData->fcSendCommandObjectInUse))
  1174.     {
  1175.         if (pb->ioMisc == (Ptr) kForkData)
  1176.             pFWXNodeData->fcSendBuffer[0] = kFCDataRequest;
  1177.         else
  1178.             pFWXNodeData->fcSendBuffer[0] = kFCControlRequest;
  1179.             
  1180.         pFWXNodeData->fcSendBuffer[2] = pFWXNodeData->fcIndex;
  1181.         pFWXNodeData->fcSendCommandObjectInUse = true;
  1182.         FWSetFWCommandCompletionProcData (pFWXNodeData->fcSendCommandObjectID, (UInt32) pFWXNodeData);
  1183.         FWSetCommonAsynchCommandParams (pFWXNodeData->fcSendCommandObjectID,
  1184.                                         pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  1185.                                         pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  1186.                                         (Ptr) pFWXNodeData->fcSendBuffer,
  1187.                                         kFlowControlSize);
  1188.         status = FWWrite(pFWXNodeData->fcSendCommandObjectID);
  1189.         if (status != noErr)
  1190.         {
  1191.             pFWXNodeData->fcSendCommandObjectInUse = false;
  1192.         }
  1193.     }
  1194.     else
  1195.     {
  1196.         sprintf(debugStr,"Error in retry flow control: %ld", status);
  1197.         FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  1198.     }
  1199.     return status;
  1200. }
  1201.  
  1202. ////////////////////////////////////////////////////////////////////////////////
  1203. //
  1204. //    SendDataPacket
  1205. //
  1206. //    Send a data packet. If the receive available packet counter is 0
  1207. //    then send a flow control request to the receiver to get the number
  1208. //    of receive buffers available.
  1209. //
  1210. static OSStatus SendDataPacket(
  1211.     FWXNodeDataPtr            pFWXNodeData,
  1212.     IOParamPtr                pb,
  1213.     UInt32                    length)
  1214. {
  1215.     OSStatus                status = noErr;
  1216.  
  1217.     if (pFWXNodeData->dataPbAvail > 0)
  1218.     {
  1219.         pFWXNodeData->dataPbAvail--;
  1220.         pFWXNodeData->writeAsynchCommandObjectInUse = true;
  1221.         FWSetFWCommandCompletionProcData (pFWXNodeData->writeAsynchCommandObjectID, (UInt32) pFWXNodeData);
  1222.         FWSetCommonAsynchCommandParams  (pFWXNodeData->writeAsynchCommandObjectID,
  1223.                                         pFWXNodeData->remoteDataAddress.addressHi,
  1224.                                         pFWXNodeData->remoteDataAddress.addressLo,
  1225.                                         pb->ioBuffer + pb->ioActCount,        // increment buffer address
  1226.                                         length);
  1227.         status = FWWrite(pFWXNodeData->writeAsynchCommandObjectID);
  1228.         if (status != noErr)
  1229.             pFWXNodeData->writeAsynchCommandObjectInUse = false;
  1230.     }
  1231.     else
  1232.     {
  1233.         pFWXNodeData->fcStopSend = true;
  1234.         
  1235.         // JKL *** can another flow control write be pending? What if there is no
  1236.         //    response?
  1237.         if (!pFWXNodeData->fcSendCommandObjectInUse)
  1238.         {
  1239.             pFWXNodeData->fcSendBuffer[0] = kFCDataRequest;
  1240.             pFWXNodeData->fcSendBuffer[2] = pFWXNodeData->fcIndex;
  1241.             pFWXNodeData->fcSendCommandObjectInUse = true;
  1242.             FWSetFWCommandCompletionProcData (pFWXNodeData->fcSendCommandObjectID, (UInt32) pFWXNodeData);
  1243.             FWSetCommonAsynchCommandParams (pFWXNodeData->fcSendCommandObjectID,
  1244.                                             pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  1245.                                             pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  1246.                                             (Ptr) pFWXNodeData->fcSendBuffer,
  1247.                                             kFlowControlSize);
  1248.             status = FWWrite(pFWXNodeData->fcSendCommandObjectID);
  1249.             if (status != noErr)
  1250.                 pFWXNodeData->fcSendCommandObjectInUse = false;
  1251.         }
  1252.     }
  1253.     return status;
  1254. }
  1255.  
  1256. ////////////////////////////////////////////////////////////////////////////////
  1257. //
  1258. //    SendControlPacket
  1259. //
  1260. //    Send a control packet. Make sure a control packet is allowed. If none
  1261. //    are allowed packet will be sent once allowed notification is received.
  1262. //
  1263.  
  1264. static OSStatus SendControlPacket(
  1265.     FWXNodeDataPtr            pFWXNodeData,
  1266.     IOParamPtr                pb,
  1267.     UInt32                    length)
  1268. {
  1269.     OSStatus                status = noErr;
  1270.  
  1271.     if (pFWXNodeData->controlPbAvail > 0)
  1272.     {
  1273.         pFWXNodeData->controlPbAvail--;
  1274.         pFWXNodeData->controlIndex++;
  1275.         *((UInt32 *) pb->ioBuffer) = pFWXNodeData->controlIndex;
  1276.         length += 4;
  1277.  
  1278.         pFWXNodeData->writeAsynchCommandObjectInUse = true;
  1279.         FWSetFWCommandCompletionProcData (pFWXNodeData->writeAsynchCommandObjectID, (UInt32) pFWXNodeData);
  1280.         FWSetCommonAsynchCommandParams (pFWXNodeData->writeAsynchCommandObjectID,
  1281.                                         pFWXNodeData->fwxUnitInfo.controlAddress.addressHi,
  1282.                                         pFWXNodeData->fwxUnitInfo.controlAddress.addressLo,
  1283.                                         pb->ioBuffer,
  1284.                                         length);
  1285.         status = FWWrite(pFWXNodeData->writeAsynchCommandObjectID);
  1286.         if (status != noErr)
  1287.             pFWXNodeData->writeAsynchCommandObjectInUse = false;
  1288.     }
  1289.     else
  1290.     {
  1291.         pFWXNodeData->fcStopSend = true;
  1292.  
  1293.         // JKL *** can another flow control write be pending? What if there is no
  1294.         //    response?
  1295.         if (!pFWXNodeData->fcSendCommandObjectInUse)
  1296.         {
  1297.             pFWXNodeData->fcSendBuffer[0] = kFCControlRequest;
  1298.             pFWXNodeData->fcSendBuffer[2] = pFWXNodeData->fcIndex;
  1299.             pFWXNodeData->fcSendCommandObjectInUse = true;
  1300.             FWSetFWCommandCompletionProcData (pFWXNodeData->fcSendCommandObjectID, (UInt32) pFWXNodeData);
  1301.             FWSetCommonAsynchCommandParams (pFWXNodeData->fcSendCommandObjectID,
  1302.                                             pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  1303.                                             pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  1304.                                             (Ptr) pFWXNodeData->fcSendBuffer,
  1305.                                             kFlowControlSize);
  1306.             status = FWWrite(pFWXNodeData->fcSendCommandObjectID);
  1307.             if (status != noErr)
  1308.                 pFWXNodeData->fcSendCommandObjectInUse = false;
  1309.         }
  1310.     }
  1311.     return status;
  1312. }
  1313.  
  1314. ////////////////////////////////////////////////////////////////////////////////
  1315. //
  1316. //    SendPacket
  1317. //
  1318. //    Check for the packet needs data to be sent. Pass it off to the senddata
  1319. //    or sendcontrol routine. If no data, complete the command.
  1320. //
  1321.  
  1322. static OSStatus SendPacket(
  1323.     FWXNodeDataPtr            pFWXNodeData)
  1324. {
  1325.     IOParamPtr                pb;
  1326.     OSStatus                status = noErr;
  1327.  
  1328.     if     (pFWXNodeData->fcStopSend)
  1329.         FWDebugStr("\pIn SendPacket with stop flow control");
  1330.  
  1331.     pb = pFWXNodeData->pCurIOParam;
  1332.     if (pb != nil) 
  1333.     {
  1334.         if (pb->ioMisc == (Ptr) kForkData)
  1335.             status = SendDataPacket(pFWXNodeData, pb, pb->ioReqCount);
  1336.         else
  1337.             status = SendControlPacket(pFWXNodeData, pb, pb->ioReqCount);
  1338.     }
  1339.  
  1340.     return status;
  1341. }
  1342.  
  1343. ////////////////////////////////////////////////////////////////////////////////
  1344. //
  1345. //    FWXDriverInterface
  1346. //
  1347. //    Main FireWire File Exchange driver interface.
  1348. //
  1349.  
  1350. OSStatus FWXDriverInterface (
  1351.     FWXInterfaceParamsPtr        pFWXInterfaceParams)
  1352. {
  1353.     FWXNodeDataPtr                pFWXNodeData;
  1354.     IOParamPtr                    pIOPB;
  1355.     UInt32                        interfaceSelector;
  1356.     OSStatus                    err = noErr;
  1357.  
  1358.     // Get our driver and node info
  1359.     pFWXNodeData =
  1360.         (FWXNodeDataPtr) pFWXInterfaceParams->pNodeSpecificData;
  1361.     interfaceSelector = pFWXInterfaceParams->interfaceSelector;
  1362.  
  1363.     // Main dispatch.
  1364.     switch (interfaceSelector) {
  1365.  
  1366.         case kFWXInitialize :
  1367.             err = FWXInitialize((FWXInitializeParamsPtr) pFWXInterfaceParams);
  1368.             break;
  1369.  
  1370.         case kFWXTerminate :
  1371.             err = FWXTerminate((FWXTerminateParamsPtr) pFWXInterfaceParams);
  1372.             break;
  1373.  
  1374.         case kFWXWrite :
  1375.             err = FWXWrite((FWXAsynchParamsPtr) pFWXInterfaceParams);
  1376.             break;
  1377.  
  1378.         case kFWXRead :
  1379.             err = FWXRead((FWXAsynchParamsPtr) pFWXInterfaceParams);
  1380.             break;
  1381.  
  1382.         case kFWXKillIO :
  1383.             pFWXNodeData->writePending = false;
  1384.             
  1385.             // clean up any pending reads
  1386.             err = PBDequeueFirst(pFWXNodeData->pReadControlQHdr, (QElemPtr *) &pIOPB);
  1387.             while ((pIOPB != nil) && (err == noErr)) {
  1388.                 pIOPB->ioActCount = 0;
  1389.                 FWXCommandIsComplete(pIOPB, noErr);
  1390.                 err = PBDequeueFirst(pFWXNodeData->pReadControlQHdr, (QElemPtr *) &pIOPB);
  1391.             }
  1392.             
  1393.             err = PBDequeueFirst(pFWXNodeData->pReadDataQHdr, (QElemPtr *) &pIOPB);
  1394.             while ((pIOPB != nil) && (err == noErr)) {
  1395.                 pIOPB->ioActCount = 0;
  1396.                 FWXCommandIsComplete(pIOPB, noErr);
  1397.                 err = PBDequeueFirst(pFWXNodeData->pReadDataQHdr, (QElemPtr *) &pIOPB);
  1398.             }
  1399.             pFWXNodeData->dataPbCount = 0;
  1400.             pFWXNodeData->controlPbCount = 0;
  1401.             pFWXNodeData->dataPbAvail = 0;
  1402.             pFWXNodeData->controlPbAvail = 0;
  1403.             break;
  1404.  
  1405.         case kFWXOpenNode:
  1406.             err = FWXOpenNode((FWXOpenNodeParamsPtr) pFWXInterfaceParams);
  1407.             break;
  1408.  
  1409.         case kFWXCloseNode:
  1410.             err = FWXCloseNode((FWXNodeDataPtr) (pFWXInterfaceParams->pNodeSpecificData));
  1411.             break;
  1412.  
  1413.         default :
  1414.             err = paramErr;
  1415.             break;
  1416.     }
  1417.  
  1418.     return err;
  1419. }
  1420.  
  1421. ////////////////////////////////////////////////////////////////////////////////
  1422. //
  1423. //    FWXInitialize
  1424. //
  1425. //    This routine initializes the FireWire File Exchange driver.  It
  1426. //    allocates a private data record and registers with the FireWire family.
  1427. //
  1428.  
  1429. static OSStatus FWXInitialize(
  1430.     FWXInitializeParamsPtr        pFWXInitializeParams)
  1431. {
  1432.     FWPDriverProtocol            fwPDriverProtocolTable[1];
  1433.     Ptr                            pBuffer = nil;
  1434.     FWXDriverDataPtr            pFWXDriverData;
  1435.     OSStatus                    status = noErr;
  1436.     
  1437. //    FWDebugStr("\pfwix driver init");
  1438.     // Allocate driver data.
  1439.     pFWXDriverData = (FWXDriverDataPtr) PoolAllocateResident(sizeof(FWXDriverData), true);
  1440.     if (pFWXDriverData != nil)
  1441.         pFWXDriverData->fwxDriverID = pFWXInitializeParams->fwxDriverID;
  1442.     else
  1443.         status = memFullErr;
  1444.  
  1445.     // Allocate a control buffer
  1446.     if (status == noErr)
  1447.     {
  1448.         pBuffer = PoolAllocateResident(kFWControlBufferSize, false);
  1449.         if (pBuffer == nil)
  1450.         {
  1451.             PoolDeallocate((Ptr) pFWXDriverData);
  1452.             pFWXDriverData = nil;
  1453.             status = memFullErr;
  1454.         }
  1455.         else
  1456.             pFWXDriverData->controlBuffer = pBuffer;
  1457.     }
  1458.  
  1459.     // Allocate a flow control receive buffer
  1460.     if (status == noErr)
  1461.     {
  1462.         pBuffer = PoolAllocateResident(kFlowControlSize, true);
  1463.         if (pBuffer == nil)
  1464.         {
  1465.             PoolDeallocate(pFWXDriverData->controlBuffer);
  1466.             PoolDeallocate((Ptr) pFWXDriverData);
  1467.             pFWXDriverData = nil;
  1468.             status = memFullErr;
  1469.         }
  1470.         else
  1471.             pFWXDriverData->fcBuffer = pBuffer;
  1472.     }
  1473.  
  1474.     // Register with the FireWire family.
  1475.     if (status == noErr)
  1476.     {
  1477.         status = FWRegisterProtocolDriver (pFWXInitializeParams->pDriverRegEntry,
  1478.                                            &(pFWXDriverData->fwPDriverID),
  1479.                                            (UInt32) pFWXDriverData);
  1480.     }
  1481.  
  1482.     // Set protocol table.
  1483.     if (status == noErr)
  1484.     {
  1485.         fwPDriverProtocolTable[0].specID = 'app';
  1486.         fwPDriverProtocolTable[0].swVersion = 'fwx';
  1487.         status = FWSetPDriverProtocolTable (pFWXDriverData->fwPDriverID,
  1488.                                             &fwPDriverProtocolTable[0],
  1489.                                             1);
  1490.     }
  1491.  
  1492.     // Set unit notification procs.
  1493.     if (status == noErr)
  1494.     {
  1495.         status = FWSetFWPDriverUnitAddedProc (pFWXDriverData->fwPDriverID,
  1496.                                               FWPDriverUnitAdded);
  1497.     }
  1498.     if (status == noErr)
  1499.     {
  1500.         status = FWSetFWPDriverUnitRemovedProc (pFWXDriverData->fwPDriverID,
  1501.                                                 FWPDriverUnitRemoved);
  1502.     }
  1503.  
  1504.     // Scan for units.
  1505.     if (status == noErr)
  1506.         status = FWScanUnitsForFWPDriver (pFWXDriverData->fwPDriverID);
  1507.  
  1508.     // set driver write notify routine
  1509.     if (status == noErr)
  1510.     {
  1511.         status = FWSetFWClientWriteCompleteProc((FWReferenceID) pFWXDriverData->fwPDriverID,
  1512.                                                 FWClientWriteCompleteInterface);
  1513.     }
  1514.  
  1515.     // Get address space for control buffer: allow write and notify on write
  1516.     if (status == noErr)
  1517.     {
  1518.         status = FWAllocateAddressSpace
  1519.                     (&pFWXDriverData->controlAddressSpaceID,
  1520.                      (FWReferenceID) pFWXDriverData->fwPDriverID,
  1521.                      &(pFWXDriverData->controlAddress),
  1522.                      kFWControlBufferSize,
  1523.                      pFWXDriverData->controlBuffer,
  1524.                      kFWAddressWriteEnable | kFWAddressWriteCompleteNotify,
  1525.                      (Ptr) pFWXDriverData);
  1526.     }
  1527.  
  1528.     // Get address space for flow control buffer: allow write, notify on write
  1529.     if (status == noErr)
  1530.     {
  1531.         status = FWAllocateAddressSpace
  1532.                     (&pFWXDriverData->fcAddressSpaceID,
  1533.                      (FWReferenceID) pFWXDriverData->fwPDriverID,
  1534.                      &(pFWXDriverData->fcAddress),
  1535.                      kFlowControlSize,
  1536.                      (Ptr) pFWXDriverData->fcBuffer,
  1537.                      kFWAddressWriteEnable | kFWAddressWriteCompleteNotify,
  1538.                      (Ptr) pFWXDriverData);
  1539.     }
  1540.  
  1541.     // Create a unit directory.
  1542.     if (status == noErr)
  1543.     {
  1544.         status = FWXCreatePDriverUnitDirectory (pFWXDriverData,
  1545.                                                 &(pFWXDriverData->unitCSRROMEntryID));
  1546.     }
  1547.  
  1548.  
  1549.     // Save our driver data or clean up on error.
  1550.     if (status == noErr)
  1551.     {
  1552.         pFWXInitializeParams->fwxInterfaceParams.pDriverSpecificData =
  1553.             (Ptr) pFWXDriverData;
  1554.     }
  1555.     else
  1556.     {
  1557.         //zzz should use terminate
  1558.         // deallocate more stuff, asynch object?
  1559.         if (pFWXDriverData->fcBuffer != nil)
  1560.             PoolDeallocate((Ptr) pFWXDriverData->fcBuffer);
  1561.         if (pFWXDriverData->controlBuffer != nil)
  1562.             PoolDeallocate(pFWXDriverData->controlBuffer);
  1563.         if (pFWXDriverData != nil)
  1564.             PoolDeallocate((Ptr) pFWXDriverData);
  1565.  
  1566.         pFWXInitializeParams->fwxInterfaceParams.pDriverSpecificData = nil;
  1567.     }
  1568.     return status;
  1569. }
  1570.  
  1571.  
  1572. ////////////////////////////////////////////////////////////////////////////////
  1573. //
  1574. // FWXCreatePDriverUnitDirectory
  1575. //
  1576. //   This routine adds a Configuration ROM unit directory for the protocol driver.
  1577. //zzz must do cleanup on error.
  1578. //
  1579.  
  1580. static OSStatus    FWXCreatePDriverUnitDirectory(
  1581.     FWXDriverDataPtr            pFWXDriverData,
  1582.     CSRROMEntryID                *pFWPDriverCSRROMUnitDirID)
  1583. {
  1584.     CSRROMEntryID                csrROMRootEntryID = kInvalidCSRROMEntryID,
  1585.                                 csrROMUnitDirEntryID = kInvalidCSRROMEntryID,
  1586.                                 csrROMEntryID = kInvalidCSRROMEntryID;
  1587.     FWXUnitInfo                    fwxUnitInfo;
  1588.     UInt32                        immediateEntry;
  1589.     OSStatus                    status = noErr;
  1590.  
  1591.     // Get configuration ROM root directory.
  1592.     status = FWCSRROMGetRootDirectory (pFWXDriverData->fwPDriverID, &csrROMRootEntryID);
  1593.  
  1594.     // Create a new unit directory.
  1595.     if (status == noErr)
  1596.     {
  1597.         status = FWCSRROMCreateEntry (csrROMRootEntryID,
  1598.                                       &csrROMUnitDirEntryID,
  1599.                                       kDirectoryCSRROMEntryType,
  1600.                                       kCSRUnitDirectoryKey,
  1601.                                       nil,
  1602.                                       0);
  1603.         if (status == noErr)
  1604.             pFWXDriverData->unitCSRROMEntryID = csrROMUnitDirEntryID;
  1605.     }
  1606.  
  1607.     // Set unit's spec ID.
  1608.     if (status == noErr)
  1609.     {
  1610.         immediateEntry = 'app ';
  1611.         status = FWCSRROMCreateEntry (csrROMUnitDirEntryID,
  1612.                                       &csrROMEntryID,
  1613.                                       kImmediateCSRROMEntryType,
  1614.                                       kCSRUnitSpecIdKey,
  1615.                                       (Ptr) &immediateEntry,
  1616.                                       3);
  1617.     }
  1618.  
  1619.     // Set unit's SW Version.
  1620.     if (status == noErr)
  1621.     {
  1622.         immediateEntry = 'fwx ';
  1623.         status = FWCSRROMCreateEntry (csrROMUnitDirEntryID,
  1624.                                       &csrROMEntryID,
  1625.                                       kImmediateCSRROMEntryType,
  1626.                                       kCSRUnitSwVersionKey,
  1627.                                       (Ptr) &immediateEntry,
  1628.                                       3);
  1629.     }
  1630.  
  1631.     // Create unit dependent leaf.
  1632.     if (status == noErr)
  1633.     {
  1634.         // Fill in data for FWiX unit info leaf.
  1635.         fwxUnitInfo.controlAddress.addressHi = pFWXDriverData->controlAddress.addressHi;
  1636.         fwxUnitInfo.controlAddress.addressLo = pFWXDriverData->controlAddress.addressLo;
  1637.         fwxUnitInfo.fcAddress.addressHi = pFWXDriverData->fcAddress.addressHi;
  1638.         fwxUnitInfo.fcAddress.addressLo = pFWXDriverData->fcAddress.addressLo;
  1639.  
  1640.         // Create the leaf.
  1641.         status = FWCSRROMCreateEntry (csrROMUnitDirEntryID,
  1642.                                       &csrROMEntryID,
  1643.                                       kLeafCSRROMEntryType,
  1644.                                       kCSRUnitDependentInfoKey,
  1645.                                       (Ptr) &fwxUnitInfo,
  1646.                                       sizeof (FWXUnitInfo));
  1647.     }
  1648.  
  1649.     // Instantiate CSR ROM.
  1650.     if (status == noErr)
  1651.         status = FWCSRROMInstantiate (pFWXDriverData->fwPDriverID);
  1652.  
  1653.     // Clean up.
  1654.     if (csrROMRootEntryID != (CSRROMEntryID) kInvalidCSRROMEntryID)
  1655.         FWCSRROMDisposeEntryID (csrROMRootEntryID);
  1656.  
  1657.     if (csrROMEntryID != (CSRROMEntryID) kInvalidCSRROMEntryID)
  1658.         FWCSRROMDisposeEntryID (csrROMEntryID);
  1659.  
  1660.     // Return unit directory ID.
  1661.     if (status == noErr)
  1662.         *pFWPDriverCSRROMUnitDirID = csrROMUnitDirEntryID;
  1663.     else
  1664.         *pFWPDriverCSRROMUnitDirID = kInvalidCSRROMEntryID;
  1665.  
  1666.     return (status);
  1667. }
  1668.  
  1669.  
  1670. ////////////////////////////////////////////////////////////////////////////////
  1671. //
  1672. //    FWXTerminate
  1673. //
  1674. //    This routine terminates the FireWire File Exchange driver.  It
  1675. //    deallocates a private data record and unregisters with the FireWire family.
  1676. //zzz need to do more deallocation:
  1677. //        xmit and receive buffers
  1678. //        CSR ROM unit dir entry
  1679. //        
  1680. //
  1681.  
  1682. static OSStatus    FWXTerminate(
  1683.     FWXTerminateParamsPtr        pFWXTerminateParams)
  1684. {
  1685.     FWXDriverDataPtr            pFWXDriverData;
  1686.     OSStatus                    status = noErr;
  1687.  
  1688. //    FWDebugStr("\pfwix driver terminate");
  1689.     // Get driver data from params.
  1690.     pFWXDriverData = (FWXDriverDataPtr)
  1691.         pFWXTerminateParams->fwxInterfaceParams.pDriverSpecificData;
  1692.  
  1693.     // Deallocate our driver data.
  1694.     if (pFWXDriverData != nil) {
  1695.  
  1696.         if (pFWXDriverData->unitCSRROMEntryID != (CSRROMEntryID) kInvalidCSRROMEntryID)
  1697.             FWCSRROMDisposeEntryID (pFWXDriverData->unitCSRROMEntryID);
  1698.  
  1699.         if (pFWXDriverData->controlBuffer != nil)
  1700.             PoolDeallocate((Ptr) pFWXDriverData->controlBuffer);
  1701.         
  1702.         if (pFWXDriverData->fcBuffer != nil)
  1703.             PoolDeallocate((Ptr) pFWXDriverData->fcBuffer);
  1704.         
  1705.         // Unregister with FireWire family.
  1706.         FWUnregisterProtocolDriver(pFWXDriverData->fwPDriverID);
  1707.  
  1708.         // Deallocate our driver data.
  1709.         PoolDeallocate((Ptr) pFWXDriverData);
  1710.     }
  1711.     
  1712.     return status;
  1713. }
  1714.  
  1715. ////////////////////////////////////////////////////////////////////////////////
  1716. //
  1717. //    FWXOpenNode
  1718. //
  1719. //    This routine opens a connections to a remote FWiX node. Allocate a bunch
  1720. //    of buffers and get the remote node's info. Have to send the node our data
  1721. //    address space for him. Use the flow control asynch object and buffers to
  1722. //    handle this. Why? Its there and the right size.
  1723. //
  1724.  
  1725. static OSStatus FWXOpenNode(
  1726.     FWXOpenNodeParamsPtr        pFWXInitializeParams)
  1727. {
  1728.     FWXDriverDataPtr            pFWXDriverData;
  1729.     FWXNodeDataPtr                pFWXNodeData = nil;
  1730.     CSRROMEntryIterator            csrROMIterator = kInvalidCSRROMIterator;
  1731.     CSRROMSearchCriteria        searchCriteria;
  1732.     CSRROMEntryID                unitCSRROMEntryID,
  1733.                                 unitInfoCSRROMEntryID = kInvalidCSRROMEntryID;
  1734.     UInt32                        unitInfoSize;
  1735.     FWCommandObjectID            asynchCommandObjectID;
  1736.     Boolean                        done;
  1737.     OSStatus                    status = noErr;
  1738.  
  1739. //    FWDebugStr("\pFWXOpenNode");
  1740.     // Get our driver data.
  1741.     pFWXDriverData = (FWXDriverDataPtr) pFWXInitializeParams->fwxInterfaceParams.pDriverSpecificData;
  1742.  
  1743.     // Allocate a node data record
  1744.     pFWXNodeData = (FWXNodeDataPtr) PoolAllocateResident (sizeof (FWXNodeData), true);
  1745.     if (pFWXNodeData != nil)
  1746.     {
  1747.         pFWXNodeData->fwUnitID =
  1748.             (FWUnitID) pFWXInitializeParams->fwxNodeRegistrationReference;
  1749.         pFWXNodeData->pFWXDriverData = pFWXDriverData;
  1750.     }
  1751.     else
  1752.         status = memFullErr;
  1753.     
  1754.     // Allocate a flow control send buffer
  1755.     if (status == noErr)
  1756.     {        
  1757.         pFWXNodeData->fcSendBuffer = (SInt32 *) PoolAllocateResident(kFlowControlSize, false);
  1758.         if (pFWXNodeData->fcSendBuffer == nil)
  1759.             status = memFullErr;
  1760.     }
  1761.  
  1762.     // Allocate a flow control reply buffer
  1763.     if (status == noErr)
  1764.     {        
  1765.         pFWXNodeData->fcReplyBuffer = (SInt32 *) PoolAllocateResident(kFlowControlSize, false);
  1766.         if (pFWXNodeData->fcReplyBuffer == nil)
  1767.         status = memFullErr;
  1768.     }
  1769.     
  1770.     // Allocate a data done buffer
  1771.     if (status == noErr)
  1772.     {        
  1773.         pFWXNodeData->dataDoneBuffer = (SInt32 *) PoolAllocateResident(kDataDoneBufSize, false);
  1774.         if (pFWXNodeData->dataDoneBuffer == nil)
  1775.         status = memFullErr;
  1776.     }
  1777.  
  1778.     // Allocate a data buffer and get address space, have to send this to the
  1779.     // node after the rest of the allocations
  1780.     if (status == noErr)
  1781.     {        
  1782.         pFWXNodeData->dataBuffer = PoolAllocateResident(kFWDataBufferSize, false);
  1783.         if (pFWXNodeData->dataBuffer != nil)
  1784.         {
  1785.             // Get address space for data buffer: allow write, notify is handled with data done message
  1786.             status = FWAllocateAddressSpace (&pFWXNodeData->localDataAddressSpaceID,
  1787.                                               (FWReferenceID) pFWXDriverData->fwPDriverID,
  1788.                                               &pFWXNodeData->localDataAddress,
  1789.                                               kFWDataBufferSize,
  1790.                                               pFWXNodeData->dataBuffer,
  1791.                                              kFWAddressWriteEnable,
  1792.                                              (Ptr) pFWXDriverData);
  1793.         }
  1794.         else
  1795.             status = memFullErr;
  1796.     }
  1797.  
  1798.     // Add node data record to driver's list.
  1799.     if (status == noErr)
  1800.     {
  1801.         if (pFWXDriverData->fwxNodeDataList != nil)
  1802.             pFWXDriverData->fwxNodeDataList->pPrevFWXNodeData = pFWXNodeData;
  1803.  
  1804.         pFWXNodeData->pPrevFWXNodeData = nil;
  1805.         pFWXNodeData->pNextFWXNodeData = pFWXDriverData->fwxNodeDataList;
  1806.  
  1807.         pFWXDriverData->fwxNodeDataList = pFWXNodeData;
  1808.     }
  1809.  
  1810.     // Get node's device ID.
  1811.     if (status == noErr)
  1812.     {
  1813.         status = FWGetFWDeviceIDFromFWReferenceID ((FWReferenceID) pFWXNodeData->fwUnitID,
  1814.                                                    &(pFWXNodeData->fwDeviceID));
  1815.     }
  1816.  
  1817.     // Get node's unit dependent information.
  1818.     if (status == noErr)
  1819.     {
  1820.         // Get unit CSR ROM entry ID.
  1821.         status = FWGetUnitCSRROMEntryID ((FWReferenceID) pFWXNodeData->fwUnitID,
  1822.                                          &unitCSRROMEntryID);
  1823.  
  1824.         // Create a CSR ROM search iterator.
  1825.         if (status == noErr) {
  1826.             status = FWCSRROMCreateIterator (&csrROMIterator,
  1827.                                              (FWReferenceID) pFWXNodeData->fwUnitID);
  1828.         }
  1829.  
  1830.         // Set iterator to start searching at our unit directory.
  1831.         if (status == noErr) {
  1832.             status = FWCSRROMSetIterator (csrROMIterator,
  1833.                                           unitCSRROMEntryID,
  1834.                                           kIterateDescendants);
  1835.         }
  1836.  
  1837.         // Search for unit dependent info leaf.
  1838.         if (status == noErr) {
  1839.             searchCriteria.csrROMSearchType = kCSRROMSearchForKey;
  1840.             searchCriteria.keyType = kCSRLeafKeyTypeBit;
  1841.             searchCriteria.keyHi = kCSRUnitDependentInfoKeyHiBit;
  1842.             searchCriteria.keyLo = kCSRUnitDependentInfoKeyLoBit;
  1843.             unitInfoSize = sizeof (FWXUnitInfo);
  1844.             status = FWCSRROMEntrySearch (csrROMIterator,
  1845.                                           kIterateContinue,
  1846.                                           &unitInfoCSRROMEntryID,
  1847.                                           &done,
  1848.                                           &searchCriteria,
  1849.                                           (Ptr) &(pFWXNodeData->fwxUnitInfo),
  1850.                                           &unitInfoSize);
  1851.         }
  1852.  
  1853.         // Clean up.
  1854.         if (csrROMIterator != (CSRROMEntryIterator) kInvalidCSRROMIterator)
  1855.             FWCSRROMDisposeIterator (csrROMIterator);
  1856.         if (unitInfoCSRROMEntryID != (CSRROMEntryIterator) kInvalidCSRROMEntryID)
  1857.             FWCSRROMDisposeEntryID (unitInfoCSRROMEntryID);
  1858.     }
  1859.  
  1860.     // Allocate FireWire command object for sending asynchronous write packets.
  1861.     if (status == noErr)
  1862.     {
  1863.         status = FWAllocateAsynchCommandObject(&asynchCommandObjectID);
  1864.         if (status == noErr)
  1865.         {
  1866.             pFWXNodeData->writeAsynchCommandObjectID = asynchCommandObjectID;
  1867.             FWSetFWCommandParams(asynchCommandObjectID,
  1868.                                  (FWReferenceID) pFWXNodeData->fwUnitID,
  1869.                                  0,
  1870.                                  FWXWriteCompletion,
  1871.                                  (UInt32) pFWXInitializeParams->fwxInterfaceParams.pDriverSpecificData);
  1872.             FWSetAsynchCommandMaxRetries(asynchCommandObjectID, 8);
  1873.         }
  1874.     }
  1875.  
  1876. #ifdef FireBug
  1877.     FireBugPrep ((FWReferenceID) pFWXNodeData->fwUnitID);
  1878.     sprintf (fireBug, "FWiX FireBug service ready on %s", "(unknown)");    // could add some kind of ID
  1879.     FireBugMsg (fireBug);
  1880. #endif
  1881.  
  1882.     // Allocate FireWire command object for sending flow control packets.
  1883.     if (status == noErr)
  1884.     {
  1885.         status = FWAllocateAsynchCommandObject(&asynchCommandObjectID);
  1886.         if (status == noErr)
  1887.         {
  1888.             pFWXNodeData->fcSendCommandObjectID = asynchCommandObjectID;
  1889.             FWSetFWCommandParams (asynchCommandObjectID,
  1890.                              (FWReferenceID) pFWXNodeData->fwUnitID,
  1891.                              0,
  1892.                 FlowControlComplete,
  1893.                 (UInt32) pFWXInitializeParams->fwxInterfaceParams.pDriverSpecificData);
  1894.         FWSetAsynchCommandMaxRetries(asynchCommandObjectID, 8);
  1895.     }
  1896.     }
  1897.  
  1898.     // Allocate FireWire command object for replying with flow control packets.
  1899.     if (status == noErr)
  1900.     {
  1901.         status = FWAllocateAsynchCommandObject(&asynchCommandObjectID);
  1902.         if (status == noErr)
  1903.         {
  1904.             pFWXNodeData->fcReplyCommandObjectID = asynchCommandObjectID;
  1905.             FWSetFWCommandParams(asynchCommandObjectID,
  1906.                 (FWReferenceID) pFWXNodeData->fwUnitID,
  1907.                 0,
  1908.                 FlowControlReplyComplete,
  1909.                 (UInt32) pFWXInitializeParams->fwxInterfaceParams.pDriverSpecificData);
  1910.             FWSetAsynchCommandMaxRetries(asynchCommandObjectID, 8);
  1911.         }
  1912.     }
  1913.  
  1914.     // setup IO queues
  1915.     if (status == noErr)
  1916.         status = SetupIOQueues(pFWXNodeData);
  1917.  
  1918.     if (status == noErr)
  1919.         FWSetMaxPayloadSize((FWReferenceID) pFWXNodeData->fwUnitID, kFWPacketSize);
  1920.  
  1921.     // Open a connection to the unit.
  1922.     if (status == noErr) {
  1923.         status = FWAddUnitConnection
  1924.                     (pFWXNodeData->fwUnitID, (FWReferenceID) pFWXDriverData->fwPDriverID);
  1925.         if (status == noErr)
  1926.             pFWXNodeData->unitConnectionAdded = true;
  1927.     }
  1928.  
  1929.     // Init control packets to some safe value, this will enable flow control to start
  1930.     if (status == noErr)
  1931.     {
  1932.         pFWXNodeData->controlPbAvail = 5;
  1933.     }
  1934.  
  1935.     // Send the data address space to the remote node using the flow control request packet
  1936.     // JKL *** can this fail, retry?
  1937.     if (status == noErr)
  1938.     {
  1939.         pFWXNodeData->fcSendCommandObjectInUse = true;
  1940.         pFWXNodeData->fcSendBuffer[0] = kAddressInfoRequest;
  1941.         pFWXNodeData->fcSendBuffer[1] = pFWXNodeData->localDataAddress.addressHi;
  1942.         pFWXNodeData->fcSendBuffer[2] = pFWXNodeData->localDataAddress.addressLo;
  1943.         FWSetFWCommandCompletionProcData (pFWXNodeData->fcSendCommandObjectID, (UInt32) pFWXNodeData);
  1944.         FWSetCommonAsynchCommandParams (pFWXNodeData->fcSendCommandObjectID,
  1945.                                         pFWXNodeData->fwxUnitInfo.fcAddress.addressHi,
  1946.                                         pFWXNodeData->fwxUnitInfo.fcAddress.addressLo,
  1947.                                         (Ptr) pFWXNodeData->fcSendBuffer,
  1948.                                         kFlowControlSize);
  1949.         status = FWWrite(pFWXNodeData->fcSendCommandObjectID);
  1950.         if (status != noErr)
  1951.             pFWXNodeData->fcSendCommandObjectInUse = false;
  1952.     }
  1953.     
  1954.     // Clean up on error.
  1955.     if (status != noErr) {
  1956.         if (pFWXNodeData != nil)
  1957.         {
  1958.             sprintf(debugStr,"Closing node from OpenNode, error: %ld", status);
  1959.             FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  1960.             FWXCloseNode (pFWXNodeData);
  1961.         }
  1962.     }
  1963.  
  1964.     // Return results.
  1965.     if (status == noErr)
  1966.         pFWXInitializeParams->fwxInterfaceParams.pNodeSpecificData = (Ptr) pFWXNodeData;
  1967.     else
  1968.         pFWXInitializeParams->fwxInterfaceParams.pNodeSpecificData = nil;
  1969.  
  1970.     return status;
  1971. }
  1972.  
  1973. ////////////////////////////////////////////////////////////////////////////////
  1974. //
  1975. //    FWXCloseNode
  1976. //
  1977. //    This routine closes a connections to a remote FWiX node.
  1978. //
  1979. static OSStatus FWXCloseNode(
  1980.     FWXNodeDataPtr                pFWXNodeData)
  1981. {
  1982.     FWXDriverDataPtr            pFWXDriverData;
  1983.     FWXNodeDataPtr                pPrevFWXNodeData,
  1984.                                 pNextFWXNodeData;
  1985.     volatile Boolean            *pFWCommandObjectInUse;
  1986.     IOParamPtr                    pIOPB;
  1987.     AbsoluteTime                timeRemaining;
  1988.     OSStatus                    status = noErr;
  1989.  
  1990. //    FWDebugStr("\pFWXCloseNode");
  1991.     if (pFWXNodeData != nil) {
  1992.         // Get our driver data.
  1993.         pFWXDriverData = (FWXDriverDataPtr) pFWXNodeData->pFWXDriverData;
  1994.  
  1995.         // Set node closed.
  1996.         pFWXNodeData->closed = true;
  1997.         CancelTimer(pFWXNodeData->fcTimerID, &timeRemaining);
  1998.  
  1999.         // Wait for all command objects to be no longer in use.
  2000.         pFWCommandObjectInUse = &(pFWXNodeData->writeAsynchCommandObjectInUse);
  2001.         while (*pFWCommandObjectInUse);
  2002.         pFWCommandObjectInUse = &(pFWXNodeData->fcSendCommandObjectInUse);
  2003.         while (*pFWCommandObjectInUse);
  2004.         pFWCommandObjectInUse = &(pFWXNodeData->fcReplyCommandObjectInUse);
  2005.         while (*pFWCommandObjectInUse);
  2006.  
  2007.         // Deallocate queues, write queue
  2008.         if (pFWXNodeData->pWriteQHdr != nil) {
  2009.             pIOPB = (IOParamPtr) pFWXNodeData->pWriteQHdr->qHead;
  2010.             while (pIOPB != nil) {
  2011.                 PBDequeueFirst(pFWXNodeData->pWriteQHdr, (QElemPtr *) &pIOPB);
  2012.                 pIOPB->ioActCount = 0;
  2013.                 FWXCommandIsComplete(pIOPB, noErr);
  2014.                 pIOPB = (IOParamPtr) pFWXNodeData->pWriteQHdr->qHead;
  2015.             }
  2016.             PBQueueDelete(pFWXNodeData->pWriteQHdr);
  2017.         }
  2018.         
  2019.         if (pFWXNodeData->pReadControlQHdr != nil) {
  2020.             pIOPB = (IOParamPtr) pFWXNodeData->pReadControlQHdr->qHead;
  2021.             while (pIOPB != nil) {
  2022.                 PBDequeueFirst(pFWXNodeData->pReadControlQHdr, (QElemPtr *) &pIOPB);
  2023.                 pIOPB->ioActCount = 0;
  2024.                 FWXCommandIsComplete(pIOPB, noErr);
  2025.                 pIOPB = (IOParamPtr) pFWXNodeData->pReadControlQHdr->qHead;
  2026.             }
  2027.             PBQueueDelete(pFWXNodeData->pReadControlQHdr);
  2028.         }
  2029.  
  2030.         if (pFWXNodeData->pReadDataQHdr != nil) {
  2031.             pIOPB = (IOParamPtr) pFWXNodeData->pReadDataQHdr->qHead;
  2032.             while (pIOPB != nil) {
  2033.                 PBDequeueFirst(pFWXNodeData->pReadDataQHdr, (QElemPtr *) &pIOPB);
  2034.                 pIOPB->ioActCount = 0;
  2035.                 FWXCommandIsComplete(pIOPB, noErr);
  2036.                 pIOPB = (IOParamPtr) pFWXNodeData->pReadDataQHdr->qHead;
  2037.             }
  2038.             PBQueueDelete(pFWXNodeData->pReadDataQHdr);
  2039.             pFWXNodeData->dataPbCount = 0;
  2040.             pFWXNodeData->controlPbCount = 0;
  2041.             pFWXNodeData->dataPbAvail = 0;
  2042.             pFWXNodeData->controlPbAvail = 0;
  2043.         }
  2044.  
  2045.         // Deallocate command object for sending asynchronous write packets.
  2046.         if (pFWXNodeData->writeAsynchCommandObjectID != (FWCommandObjectID) kInvalidFWCommandObjectID)
  2047.             FWDeallocateFWCommandObject (pFWXNodeData->writeAsynchCommandObjectID);
  2048.  
  2049.         // Deallocate command objects for flow control packets.
  2050.         if (pFWXNodeData->fcSendCommandObjectID != (FWCommandObjectID) kInvalidFWCommandObjectID)
  2051.             FWDeallocateFWCommandObject (pFWXNodeData->fcSendCommandObjectID);
  2052.         if (pFWXNodeData->fcReplyCommandObjectID != (FWCommandObjectID) kInvalidFWCommandObjectID)
  2053.             FWDeallocateFWCommandObject (pFWXNodeData->fcReplyCommandObjectID);
  2054.  
  2055.         // Remove node data record from driver's list.
  2056.         pPrevFWXNodeData = pFWXNodeData->pPrevFWXNodeData;
  2057.         pNextFWXNodeData = pFWXNodeData->pNextFWXNodeData;
  2058.  
  2059.         // Remove our connection to unit.
  2060.         if (pFWXNodeData->unitConnectionAdded) {
  2061.             FWRemoveUnitConnection (pFWXNodeData->fwUnitID,
  2062.                                     (FWReferenceID) pFWXDriverData->fwPDriverID);
  2063.         }
  2064.  
  2065.         if (pPrevFWXNodeData != nil) {
  2066.             pPrevFWXNodeData->pNextFWXNodeData = pNextFWXNodeData;
  2067.         } else {
  2068.             if (pFWXDriverData->fwxNodeDataList == pFWXNodeData)
  2069.                 pFWXDriverData->fwxNodeDataList = pNextFWXNodeData;
  2070.         }
  2071.  
  2072.         if (pNextFWXNodeData != nil)
  2073.             pNextFWXNodeData->pPrevFWXNodeData = pPrevFWXNodeData;
  2074.  
  2075.         // Deallocate buffers
  2076.         if (pFWXNodeData->fcSendBuffer != nil)
  2077.             PoolDeallocate ((Ptr) pFWXNodeData->fcSendBuffer);
  2078.         if (pFWXNodeData->fcReplyBuffer != nil)
  2079.             PoolDeallocate ((Ptr) pFWXNodeData->fcReplyBuffer);
  2080.         if (pFWXNodeData->dataDoneBuffer != nil)
  2081.             PoolDeallocate ((Ptr) pFWXNodeData->dataDoneBuffer);
  2082.         if (pFWXNodeData->dataBuffer != nil)
  2083.             PoolDeallocate((Ptr) pFWXNodeData->dataBuffer);
  2084.  
  2085.         // Deallocate address space
  2086.         FWDeallocateAddressSpace(pFWXNodeData->localDataAddressSpaceID);
  2087.  
  2088.         // Deallocate node data record.
  2089.         PoolDeallocate ((Ptr) pFWXNodeData);
  2090.     }
  2091.  
  2092.     return status;
  2093. }
  2094.  
  2095. //////////////////////////////////////////////////////////////////////////////
  2096. //
  2097. //    SetupIOQueues
  2098. //
  2099. //    Setup the queueus. Create and initialize.
  2100. //
  2101. static OSStatus SetupIOQueues(
  2102.     FWXNodeDataPtr        pFWXNodeData)
  2103. {
  2104.     OSStatus            status = noErr;
  2105.     
  2106.     status = PBQueueCreate(& pFWXNodeData->pReadDataQHdr);
  2107.     if (status == noErr)
  2108.         PBQueueInit(pFWXNodeData->pReadDataQHdr);
  2109.     else
  2110.         return status;
  2111.         
  2112.     status = PBQueueCreate(& pFWXNodeData->pReadControlQHdr);
  2113.     if (status == noErr)
  2114.         PBQueueInit(pFWXNodeData->pReadControlQHdr);
  2115.     else
  2116.         return status;
  2117.         
  2118.         status = PBQueueCreate(& pFWXNodeData->pWriteQHdr);
  2119.         if (status == noErr)
  2120.             PBQueueInit(pFWXNodeData->pWriteQHdr);
  2121.     
  2122.     return status;    
  2123. }    
  2124.  
  2125. //////////////////////////////////////////////////////////////////////////////
  2126. //
  2127. //    FWXGetNodeDataFromNodeID
  2128. //
  2129. //    Return the FWX node data record that matches the given node ID.
  2130. //
  2131. static OSStatus FWXGetNodeDataFromNodeID (
  2132.     FWXDriverDataPtr            pFWXDriverData,
  2133.     UInt32                        generation,
  2134.     UInt32                        nodeID,
  2135.     FWXNodeDataPtr                *ppFWXNodeData)
  2136. {
  2137.     FWXNodeDataPtr                pFWXNodeData;
  2138.     FWDeviceID                    fwDeviceID;
  2139.     Boolean                        found;
  2140.     OSStatus                    status = noErr;
  2141.  
  2142.     // Get FireWire device ID for nodeID.
  2143.     status = FWFindFWDeviceFromNodeID (pFWXDriverData->fwPDriverID,
  2144.                                        generation,
  2145.                                        nodeID,
  2146.                                        &fwDeviceID);
  2147.  
  2148.     // Search node data list for node with matching deviceID.
  2149.     if (status == noErr) {
  2150.         pFWXNodeData = pFWXDriverData->fwxNodeDataList;
  2151.         found = false;
  2152.         while ((pFWXNodeData != nil) && (!found))
  2153.         {
  2154.             if ((pFWXNodeData->fwDeviceID == fwDeviceID) && (!(pFWXNodeData->closed)))
  2155.                 found = true;
  2156.             else
  2157.                 pFWXNodeData = pFWXNodeData->pNextFWXNodeData;
  2158.         }
  2159.     }
  2160.  
  2161.     // Return results.
  2162.     if (status == noErr) {
  2163.         if (found) {
  2164.             *ppFWXNodeData = pFWXNodeData;
  2165.         } else {
  2166.             *ppFWXNodeData = nil;
  2167.             status = notFoundErr;
  2168.         }
  2169.     } else {
  2170.         *ppFWXNodeData = nil;
  2171.     }
  2172.  
  2173.     return (status);
  2174. }
  2175.